﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using UtilZ.Dotnet.Ex.Model;

namespace UtilZ.Dotnet.Ex.Base
{
    /// <summary>
    /// Enumerable扩展类
    /// </summary>
    unsafe public partial class EnumerableEx
    {
        /// <summary>
        /// 判断当前数据往期是否需要使用线程池多线程并行处理[返回true,需要多线程并行处理,false,则为当前线程单线程处理]
        /// </summary>
        /// <param name="length">判断依据,要处理数据长度</param>
        /// <returns>返回true,需要多线程并行处理,false,则为当前线程单线程处理</returns>
        private static bool HasParallel(int length)
        {
            return length >= 100000;
        }


        #region FindCollection

        /// <summary>
        /// 在一个集合中查找另一个集合第一次出现的索引,找到则返回首次出现目标集合的索引，未找到则返回-1
        /// </summary>
        /// <param name="source">源集合</param>
        /// <param name="target">要查找的目标集合</param>
        /// <returns>找到则返回首次出现目标集合的索引，未找到则返回-1</returns>
        public static int FindCollection(SpanZ<byte> source, SpanZ<byte> target)
        {
            int targetCount = target.Length;
            if (targetCount == 0)
            {
                throw new ArgumentException(nameof(target), "要查找的目标集合不能为空");
            }

            int index = -1;
            if (source.Length < targetCount)
            {
                return index;
            }

            int maxIndex = source.Length - targetCount + 1;
            if (maxIndex < 0)
            {
                return index;
            }

            bool flag;
            for (int i = 0; i < maxIndex; i++)
            {
                if (source[i] == target[0])
                {
                    flag = true;
                    for (int j = 1; j < targetCount; j++)
                    {
                        if (source[i + j] != target[j])
                        {
                            flag = false;
                            break;
                        }
                    }

                    if (flag)
                    {
                        index = i;
                        break;
                    }
                }
            }

            return index;
        }

        /// <summary>
        /// 在一个集合中查找另一个集合第一次出现的索引,找到则返回首次出现目标集合的索引，未找到则返回-1
        /// </summary>
        /// <param name="source">源集合</param>
        /// <param name="target">要查找的目标集合</param>
        /// <returns>找到则返回首次出现目标集合的索引，未找到则返回-1</returns>
        public static int FindCollection(SpanZ<byte> source, byte[] target)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            if (target.Length == 0)
            {
                return -1;
            }

            int targetCount = target.Length;
            if (targetCount == 0)
            {
                throw new ArgumentException(nameof(target), "要查找的目标集合不能为空");
            }

            int index = -1;
            if (source.Length < targetCount)
            {
                return index;
            }

            int maxIndex = source.Length - targetCount + 1;
            if (maxIndex < 0)
            {
                return index;
            }

            bool flag;
            for (int i = 0; i < maxIndex; i++)
            {
                if (source[i] == target[0])
                {
                    flag = true;
                    for (int j = 1; j < targetCount; j++)
                    {
                        if (source[i + j] != target[j])
                        {
                            flag = false;
                            break;
                        }
                    }

                    if (flag)
                    {
                        index = i;
                        break;
                    }
                }
            }

            return index;
        }

        /// <summary>
        /// 在一个集合中查找另一个集合第一次出现的索引,找到则返回首次出现目标集合的索引，未找到则返回-1
        /// </summary>
        /// <param name="source">源集合</param>
        /// <param name="target">要查找的目标集合</param>
        /// <returns>找到则返回首次出现目标集合的索引，未找到则返回-1</returns>
        public static int FindCollection(Span<byte> source, Span<byte> target)
        {
            int targetCount = target.Length;
            if (targetCount == 0)
            {
                throw new ArgumentException(nameof(target), "要查找的目标集合不能为空");
            }

            int index = -1;
            if (source.Length < targetCount)
            {
                return index;
            }

            int maxIndex = source.Length - targetCount + 1;
            if (maxIndex < 0)
            {
                return index;
            }

            bool flag;
            for (int i = 0; i < maxIndex; i++)
            {
                if (source[i] == target[0])
                {
                    flag = true;
                    for (int j = 1; j < targetCount; j++)
                    {
                        if (source[i + j] != target[j])
                        {
                            flag = false;
                            break;
                        }
                    }

                    if (flag)
                    {
                        index = i;
                        break;
                    }
                }
            }

            return index;
        }

        /// <summary>
        /// 在一个集合中查找另一个集合第一次出现的索引,找到则返回首次出现目标集合的索引，未找到则返回-1
        /// </summary>
        /// <param name="source">源集合</param>
        /// <param name="target">要查找的目标集合</param>
        /// <returns>找到则返回首次出现目标集合的索引，未找到则返回-1</returns>
        public static int FindCollection(Span<byte> source, byte[] target)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            if (target.Length == 0)
            {
                return -1;
            }

            int targetCount = target.Length;
            if (targetCount == 0)
            {
                throw new ArgumentException(nameof(target), "要查找的目标集合不能为空");
            }

            int index = -1;
            if (source.Length < targetCount)
            {
                return index;
            }

            int maxIndex = source.Length - targetCount + 1;
            if (maxIndex < 0)
            {
                return index;
            }

            bool flag;
            for (int i = 0; i < maxIndex; i++)
            {
                if (source[i] == target[0])
                {
                    flag = true;
                    for (int j = 1; j < targetCount; j++)
                    {
                        if (source[i + j] != target[j])
                        {
                            flag = false;
                            break;
                        }
                    }

                    if (flag)
                    {
                        index = i;
                        break;
                    }
                }
            }

            return index;
        }


        /// <summary>
        /// 在一个集合中查找另一个集合第一次出现的索引,找到则返回首次出现目标集合的索引，未找到则返回-1
        /// </summary>
        /// <param name="source">源集合</param>
        /// <param name="target">要查找的目标集合</param>
        /// <returns>找到则返回首次出现目标集合的索引，未找到则返回-1</returns>
        public static int FindCollection<T>(SpanZ<T> source, SpanZ<T> target)
            where T : struct, IComparable
        {
            int targetCount = target.Length;
            if (targetCount == 0)
            {
                throw new ArgumentException(nameof(target), "要查找的目标集合不能为空");
            }

            int index = -1;
            if (source.Length < targetCount)
            {
                return index;
            }

            int maxIndex = source.Length - targetCount + 1;
            if (maxIndex < 0)
            {
                return index;
            }

            bool flag;
            for (int i = 0; i < maxIndex; i++)
            {
                if (source[i].CompareTo(target[0]) == 0)
                {
                    flag = true;
                    for (int j = 1; j < targetCount; j++)
                    {
                        if (source[i + j].CompareTo(target[j]) != 0)
                        {
                            flag = false;
                            break;
                        }
                    }

                    if (flag)
                    {
                        index = i;
                        break;
                    }
                }
            }

            return index;
        }

        /// <summary>
        /// 在一个集合中查找另一个集合第一次出现的索引,找到则返回首次出现目标集合的索引，未找到则返回-1
        /// </summary>
        /// <param name="source">源集合</param>
        /// <param name="target">要查找的目标集合</param>
        /// <returns>找到则返回首次出现目标集合的索引，未找到则返回-1</returns>
        public static int FindCollection<T>(SpanZ<T> source, T[] target)
            where T : struct, IComparable
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            if (target.Length == 0)
            {
                return -1;
            }

            int targetCount = target.Length;
            if (targetCount == 0)
            {
                throw new ArgumentException(nameof(target), "要查找的目标集合不能为空");
            }

            int index = -1;
            if (source.Length < targetCount)
            {
                return index;
            }

            int maxIndex = source.Length - targetCount + 1;
            if (maxIndex < 0)
            {
                return index;
            }

            bool flag;
            for (int i = 0; i < maxIndex; i++)
            {
                if (source[i].CompareTo(target[0]) == 0)
                {
                    flag = true;
                    for (int j = 1; j < targetCount; j++)
                    {
                        if (source[i + j].CompareTo(target[j]) != 0)
                        {
                            flag = false;
                            break;
                        }
                    }

                    if (flag)
                    {
                        index = i;
                        break;
                    }
                }
            }

            return index;
        }


        /// <summary>
        /// 在一个集合中查找另一个集合第一次出现的索引,找到则返回首次出现目标集合的索引，未找到则返回-1
        /// </summary>
        /// <typeparam name="T">集合项类型，必须实现IComparable接口</typeparam>
        /// <param name="source">源集合</param>
        /// <param name="target">要查找的目标集合</param>
        /// <returns>找到则返回首次出现目标集合的索引，未找到则返回-1</returns>
        public static int FindCollection<T>(Span<T> source, Span<T> target) where T : struct, IComparable
        {
            int targetCount = target.Length;
            if (targetCount == 0)
            {
                throw new ArgumentException(nameof(target), "要查找的目标集合不能为空");
            }

            int index = -1;
            if (source.Length < targetCount)
            {
                return index;
            }

            int maxIndex = source.Length - targetCount + 1;
            if (maxIndex < 0)
            {
                return index;
            }

            bool flag;
            for (int i = 0; i < maxIndex; i++)
            {
                if (source[i].CompareTo(target[0]) == 0)
                {
                    flag = true;
                    for (int j = 1; j < targetCount; j++)
                    {
                        if (source[i + j].CompareTo(target[j]) != 0)
                        {
                            flag = false;
                            break;
                        }
                    }

                    if (flag)
                    {
                        index = i;
                        break;
                    }
                }
            }

            return index;
        }

        /// <summary>
        /// 在一个集合中查找另一个集合第一次出现的索引,找到则返回首次出现目标集合的索引，未找到则返回-1
        /// </summary>
        /// <typeparam name="T">集合项类型，必须实现IComparable接口</typeparam>
        /// <param name="source">源集合</param>
        /// <param name="target">要查找的目标集合</param>
        /// <returns>找到则返回首次出现目标集合的索引，未找到则返回-1</returns>
        public static int FindCollection<T>(Span<T> source, T[] target) where T : struct, IComparable
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            if (target.Length == 0)
            {
                return -1;
            }

            int targetCount = target.Length;
            if (targetCount == 0)
            {
                throw new ArgumentException(nameof(target), "要查找的目标集合不能为空");
            }

            int index = -1;
            if (source.Length < targetCount)
            {
                return index;
            }

            int maxIndex = source.Length - targetCount + 1;
            if (maxIndex < 0)
            {
                return index;
            }

            bool flag;
            for (int i = 0; i < maxIndex; i++)
            {
                if (source[i].CompareTo(target[0]) == 0)
                {
                    flag = true;
                    for (int j = 1; j < targetCount; j++)
                    {
                        if (source[i + j].CompareTo(target[j]) != 0)
                        {
                            flag = false;
                            break;
                        }
                    }

                    if (flag)
                    {
                        index = i;
                        break;
                    }
                }
            }

            return index;
        }


        /// <summary>
        /// 在一个集合中查找另一个集合第一次出现的索引,找到则返回首次出现目标集合的索引，未找到则返回-1
        /// </summary>
        /// <typeparam name="T">集合项类型，必须实现IComparable接口</typeparam>
        /// <param name="source">源集合</param>
        /// <param name="offset">源集合中的起始位置</param>
        /// <param name="findLength">源集合中查找长度</param>
        /// <param name="target">要查找的目标集合</param>
        /// <returns>找到则返回首次出现目标集合的索引，未找到则返回-1</returns>
        public static int FindCollection<T>(IEnumerable<T> source, int offset, int findLength, IEnumerable<T> target) where T : IComparable
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }

            if (findLength < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(findLength));
            }

            if (offset + findLength > source.Count())
            {
                throw new ArgumentOutOfRangeException(nameof(findLength), "源集合中的起始位置+源集合中查找长度超出了源数据范围");
            }

            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            int targetCount = target.Count();
            if (targetCount == 0)
            {
                throw new ArgumentException(nameof(target), "要查找的目标集合不能为空");
            }

            int index = -1;
            if (findLength < targetCount)
            {
                return index;
            }


            /*****************************************************************
             * offset=2, findLength=20
             * 
             * 00000000 00000000 00000000 0000000 00000000 00000000 00000000
             *   ^                    ^
             * offset           offset+findLength
             *****************************************************************/

            int maxIndex = offset + findLength - targetCount + 1;
            if (maxIndex < 0)
            {
                return index;
            }

            bool flag;
            for (int i = offset; i < maxIndex; i++)
            {
                if (source.ElementAt(i).CompareTo(target.ElementAt(0)) == 0)
                {
                    flag = true;
                    for (int j = 1; j < targetCount; j++)
                    {
                        if (source.ElementAt(i + j).CompareTo(target.ElementAt(j)) != 0)
                        {
                            flag = false;
                            break;
                        }
                    }

                    if (flag)
                    {
                        index = i;
                        break;
                    }
                }
            }

            return index;
        }

        #endregion





        /// <summary>
        /// 检查集合操作部分区域范围,返回操作结尾索引(不包含)
        /// </summary>
        /// <param name="collectionLength">集合数据长度</param>
        /// <param name="startIndex">集合中的起始位置,小于0表示从0开始</param>
        /// <param name="count">集合中的元素个数,小于0表示到结尾</param>
        /// <returns>操作结尾索引(不包含)</returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static int CheckCollectionPartRangePara(int collectionLength, ref int startIndex, ref int count)
        {
            if (startIndex < 0)
            {
                startIndex = 0;
            }
            else
            {
                if (startIndex >= collectionLength)
                {
                    throw new ArgumentOutOfRangeException(nameof(startIndex), "起始索引超出范围");
                }
            }

            int endIndex;
            if (count < 0)
            {
                count = collectionLength;
                endIndex = collectionLength;
            }
            else
            {
                endIndex = startIndex + count;
                if (endIndex > collectionLength)
                {
                    throw new ArgumentOutOfRangeException(nameof(count), "元素数超出数组范围");
                }
            }

            return endIndex;
        }

        /// <summary>
        /// 检查集合操作部分区域范围,返回操作结尾索引(不包含)
        /// </summary>
        /// <param name="collectionLength">集合数据长度</param>
        /// <param name="startIndex">集合中的起始位置,小于0表示从0开始</param>
        /// <param name="count">集合中的元素个数,小于0表示到结尾</param>
        /// <returns>操作结尾索引(不包含)</returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static long CheckCollectionPartRangePara(long collectionLength, ref long startIndex, long count)
        {
            if (startIndex < 0)
            {
                startIndex = 0;
            }
            else
            {
                if (startIndex >= collectionLength)
                {
                    throw new ArgumentOutOfRangeException(nameof(startIndex), "起始索引超出范围");
                }
            }

            long endIndex;
            if (count < 0)
            {
                endIndex = collectionLength;
            }
            else
            {
                endIndex = startIndex + count;
                if (endIndex > collectionLength)
                {
                    throw new ArgumentOutOfRangeException(nameof(count), "元素数超出数组范围");
                }
            }

            return endIndex;
        }



        #region Reverse

        /// <summary>
        /// 反转集合中的项
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="list">要反转的集合</param>
        /// <exception cref="ArgumentNullException">集合为null异常</exception>
        public static void Reverse<T>(IList<T> list)
        {
            if (list == null)
            {
                throw new ArgumentNullException(nameof(list));
            }

            int leftIndex = 0, rightIndex = list.Count - 1;
            T tmp;
            while (leftIndex < rightIndex)
            {
                tmp = list[leftIndex];
                list[leftIndex] = list[rightIndex];
                list[rightIndex] = tmp;
                leftIndex++;
                rightIndex--;
            }
        }

        /// <summary>
        /// 反转source集合中的项到destination集合
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="source">需要反转的集合</param>
        /// <param name="destination">反转结果存放集合</param>
        /// <exception cref="ArgumentNullException">source或destination为null异常</exception>
        /// <exception cref="ArgumentOutOfRangeException">source与destination长度不一致异常</exception>
        public static void Reverse<T>(IList<T> source, IList<T> destination)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (destination == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (source.Count != destination.Count)
            {
                throw new ArgumentOutOfRangeException("源数组长度与目录数组长度不一致", nameof(source));
            }

            int leftIndex = 0, rightIndex = source.Count - 1;
            while (leftIndex < rightIndex)
            {
                destination[leftIndex] = source[rightIndex];
                destination[rightIndex] = source[leftIndex];
                leftIndex++;
                rightIndex--;
            }
        }

        /// <summary>
        /// 反转source集合中的项到destination集合
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="source">需要反转的集合</param>
        /// <param name="sourceIndex">需要反转的集合起始位置索引</param>
        /// <param name="destination">目标集合</param>
        /// <param name="destinationIndex">目标集合起始位置索引</param>
        /// <param name="length">反转数据长度</param>
        /// <exception cref="ArgumentNullException">source或destination为null异常</exception>
        /// <exception cref="ArgumentOutOfRangeException">反转source集合或目标集合起始位置索引无效或长度超出范围异常</exception>
        public static void Reverse<T>(IList<T> source, int sourceIndex, IList<T> destination, int destinationIndex, int length)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (destination == null)
            {
                throw new ArgumentNullException(nameof(destination));
            }

            if (sourceIndex < 0 || sourceIndex >= source.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(sourceIndex));
            }

            if (sourceIndex + length > source.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            if (destinationIndex < 0 || destinationIndex >= destination.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationIndex));
            }

            if (destinationIndex + length > destination.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            int leftIndex = sourceIndex, rightIndex = sourceIndex + length - 1;
            int destinationIndexOffset = destinationIndex - sourceIndex;

            while (leftIndex < rightIndex)
            {
                destination[rightIndex + destinationIndexOffset] = source[leftIndex];
                destination[leftIndex + destinationIndexOffset] = source[rightIndex];
                leftIndex++;
                rightIndex--;
            }
        }

        #endregion




        #region ComplexToReal

        /// <summary>
        /// 将复数集合实部转换为实数集合
        /// </summary>
        /// <param name="source">复数集合</param>
        /// <returns>实数集合</returns>
        /// <exception cref="ArgumentNullException">复数集合为null异常</exception>
        public static double[] ComplexToReal(IList<Complex> source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            double[] destination = new double[source.Count];
            PrimitiveComplexToReal(source, 0, destination, 0, source.Count, 0);
            return destination;
        }

        /// <summary>
        /// 将复数集合实部转换为实数集合
        /// </summary>
        /// <param name="source">复数集合</param>
        /// <param name="destination">实数集合</param>
        /// <exception cref="ArgumentNullException">实数或复数集合为null异常</exception>
        public static void ComplexToReal(IList<Complex> source, IList<double> destination)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (destination == null)
            {
                throw new ArgumentNullException(nameof(destination));
            }

            int length = source.Count < destination.Count ? source.Count : destination.Count;
            PrimitiveComplexToReal(source, 0, destination, 0, length, 0);
        }

        /// <summary>
        /// 将复数集合实部转换为实数集合
        /// </summary>
        /// <param name="source">复数集合</param>
        /// <param name="sourceIndex">复数集合起始位置索引</param>
        /// <param name="destination">实数集合</param>
        /// <param name="destinationIndex">实数集合起始位置索引</param>
        /// <param name="length">转换数据长度</param>
        /// <exception cref="ArgumentNullException">实数或复数集合为null异常</exception>
        /// <exception cref="ArgumentOutOfRangeException">实数或复数起始位置索引无效或长度超出范围异常</exception>
        public static void ComplexToReal(IList<Complex> source, int sourceIndex, IList<double> destination, int destinationIndex, int length)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (destination == null)
            {
                throw new ArgumentNullException(nameof(destination));
            }

            if (sourceIndex < 0 || sourceIndex >= source.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(sourceIndex));
            }

            if (sourceIndex + length > source.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            if (destinationIndex < 0 || destinationIndex >= destination.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationIndex));
            }

            if (destinationIndex + length > destination.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            PrimitiveComplexToReal(source, sourceIndex, destination, destinationIndex, length, destinationIndex - sourceIndex);
        }

        private static void PrimitiveComplexToReal(IList<Complex> source, int sourceIndex, IList<double> destination, int destinationIndex, int length, int destinationIndexOffset)
        {
            int maxIndex = sourceIndex + length;
            if (HasParallel(length))
            {
                Parallel.For(sourceIndex, maxIndex, (i) =>
                {
                    destination[destinationIndexOffset + i] = source[i].Real;
                });
            }
            else
            {
                for (int i = sourceIndex; i < maxIndex; i++)
                {
                    destination[destinationIndexOffset + i] = source[i].Real;
                }
            }
        }

        #endregion



        #region RealToComplex

        /// <summary>
        /// 实数集合转换为复数集合,其中原数据为实部,虚部为0
        /// </summary>
        /// <param name="source">实数集合</param>
        /// <returns>复数集合</returns>
        /// <exception cref="ArgumentNullException">实数集合为null异常</exception>
        public static Complex[] RealToComplex(IList<double> source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            Complex[] destination = new Complex[source.Count];
            PrimitiveRealToComplex(source, 0, destination, source.Count, 0);
            return destination;
        }

        /// <summary>
        /// 实数集合转换为复数集合,其中原数据为实部,虚部为0
        /// </summary>
        /// <param name="source">实数集合</param>
        /// <param name="destination">复数集合</param>
        /// <exception cref="ArgumentNullException">实数或复数集合为null异常</exception>
        public static void RealToComplex(IList<double> source, IList<Complex> destination)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (destination == null)
            {
                throw new ArgumentNullException(nameof(destination));
            }

            int length = source.Count < destination.Count ? source.Count : destination.Count;
            PrimitiveRealToComplex(source, 0, destination, length, 0);
        }

        /// <summary>
        /// 实数集合转换为复数集合,其中原数据为实部,虚部为0
        /// </summary>
        /// <param name="source">实数集合</param>
        /// <param name="sourceIndex">实数集合起始位置索引</param>
        /// <param name="destination">复数集合</param>
        /// <param name="destinationIndex">复数集合起始位置索引</param>
        /// <param name="length">转换数据长度</param>
        /// <exception cref="ArgumentNullException">实数或复数集合为null异常</exception>
        /// <exception cref="ArgumentOutOfRangeException">实数或复数起始位置索引无效或长度超出范围异常</exception>
        public static void RealToComplex(IList<double> source, int sourceIndex, IList<Complex> destination, int destinationIndex, int length)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (destination == null)
            {
                throw new ArgumentNullException(nameof(destination));
            }

            if (sourceIndex < 0 || sourceIndex >= source.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(sourceIndex));
            }

            if (sourceIndex + length > source.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            if (destinationIndex < 0 || destinationIndex >= destination.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationIndex));
            }

            if (destinationIndex + length > destination.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            PrimitiveRealToComplex(source, sourceIndex, destination, length, destinationIndex - sourceIndex);
        }

        private static void PrimitiveRealToComplex(IList<double> source, int sourceIndex, IList<Complex> destination, int length, int destinationIndexOffset)
        {
            int maxIndex = sourceIndex + length;
            if (HasParallel(length))
            {
                Parallel.For(sourceIndex, maxIndex, (i) =>
                {
                    destination[destinationIndexOffset + i] = new Complex(source[i], 0d);
                });
            }
            else
            {
                for (int i = sourceIndex; i < maxIndex; i++)
                {
                    destination[destinationIndexOffset + i] = new Complex(source[i], 0d);
                }
            }
        }

        #endregion



        #region IQ转换为Real


        /// <summary>
        /// 将IQ数据转换为实数
        /// </summary>
        /// <param name="iDatas">I数据</param>
        /// <param name="qDatas">Q数据</param>
        /// <returns>实数数据存放数组</returns>
        /// <exception cref="ArgumentNullException">原始数组为null异常</exception>
        public static Int16[] IQMerge(Int16[] iDatas, Int16[] qDatas)
        {
            if (iDatas == null)
            {
                throw new ArgumentNullException(nameof(iDatas));
            }

            if (qDatas == null)
            {
                throw new ArgumentNullException(nameof(qDatas));
            }

            int count = iDatas.Length > qDatas.Length ? iDatas.Length : qDatas.Length;
            Int16[] realDatas = new short[count];
            IQMerge(iDatas, qDatas, 0, realDatas, 0, count);
            return realDatas;
        }

        /// <summary>
        /// 将IQ数据转换为实数
        /// </summary>
        /// <param name="iDatas">I数据</param>
        /// <param name="qDatas">Q数据</param>
        /// <param name="realDatas">实数数据存放数组</param>
        /// <exception cref="ArgumentNullException">原始数组或实数数组为null异常</exception>
        public static void IQMerge(Int16[] iDatas, Int16[] qDatas, Int16[] realDatas)
        {
            if (iDatas == null)
            {
                throw new ArgumentNullException(nameof(iDatas));
            }

            if (qDatas == null)
            {
                throw new ArgumentNullException(nameof(qDatas));
            }

            if (realDatas == null)
            {
                throw new ArgumentNullException(nameof(realDatas));
            }

            int len = iDatas.Length < qDatas.Length ? iDatas.Length : qDatas.Length;
            if (len > realDatas.Length)
            {
                len = realDatas.Length;
            }

            int count = len - (len % 2);//保证count值是个偶数
            IQMerge(iDatas, qDatas, 0, realDatas, 0, count);
        }

        /// <summary>
        /// 将IQ数据转换为实数
        /// </summary>
        /// <param name="iDatas">I数据</param>
        /// <param name="qDatas">Q数据</param>
        /// <param name="sourceIndex">IQ数据起始位置</param>
        /// <param name="realDatas">实数数据存放数组</param>
        /// <param name="destinationIndex">实数数据存放起始位置</param>
        /// <param name="length">转换数据长度</param>
        /// <exception cref="ArgumentNullException">原始数组或实数数组为null异常</exception>
        /// <exception cref="ArgumentOutOfRangeException">起始位置或长度超出范围异常</exception>
        public static void IQMerge(Int16[] iDatas, Int16[] qDatas, int sourceIndex, Int16[] realDatas, int destinationIndex, int length)
        {
            if (iDatas == null)
            {
                throw new ArgumentNullException(nameof(iDatas));
            }

            if (qDatas == null)
            {
                throw new ArgumentNullException(nameof(qDatas));
            }

            if (realDatas == null)
            {
                throw new ArgumentNullException(nameof(realDatas));
            }

            if (sourceIndex < 0)
            {
                throw new ArgumentOutOfRangeException("原数据起始索引不能小于0", nameof(sourceIndex));
            }

            if (destinationIndex < 0)
            {
                throw new ArgumentOutOfRangeException("结果数据起始索引不能小于0", nameof(destinationIndex));
            }

            if (length % 2 != 0)
            {
                throw new ArgumentException("处理的数据长度值必须为偶数", nameof(length));
            }

            int sourceEndIndex = sourceIndex + length;
            if (sourceEndIndex > iDatas.Length ||
                sourceEndIndex > qDatas.Length ||
                destinationIndex + length > realDatas.Length)
            {
                throw new ArgumentOutOfRangeException("处理的数据长度超出原数组长度或结果数组长度", nameof(length));
            }

            //如果数据长度超过门限个点,则用多线程并处处理,否则就单线程处理
            if (HasParallel(length))
            {
                int parallelCount = Environment.ProcessorCount;
                int segLength = length / parallelCount;
                segLength = segLength - segLength % 2;
                Parallel.For(0, parallelCount, (segIndex) =>
                {
                    int startIndex = sourceIndex + segIndex * segLength;
                    int endIndex;
                    if (segIndex + 1 == parallelCount)
                    {
                        endIndex = sourceIndex + length;//最后一个线程,要把不能平均分配的都处理掉
                    }
                    else
                    {
                        endIndex = startIndex + segLength;//非最后一个线程,只处理对应段数据
                    }
                    Console.WriteLine($"第{segIndex}段:{startIndex}-{endIndex}");
                    bool flag = true;
                    int retIndex = destinationIndex + segIndex * segLength;
                    for (int i = sourceIndex; i < sourceEndIndex; i += 2)
                    {
                        if (flag)
                        {
                            realDatas[retIndex] = iDatas[i];
                            realDatas[retIndex + 1] = (Int16)(-1 * qDatas[i + 1]);
                        }
                        else
                        {
                            realDatas[retIndex] = (Int16)(-1 * iDatas[i]);
                            realDatas[retIndex + 1] = qDatas[i + 1];
                        }
                        flag = !flag;
                        retIndex += 2;
                    }
                });
            }
            else
            {
                bool flag = true;
                int retIndex = destinationIndex;
                for (int i = sourceIndex; i < sourceEndIndex; i += 2)
                {
                    if (flag)
                    {
                        realDatas[retIndex] = iDatas[i];
                        realDatas[retIndex + 1] = (Int16)(-1 * qDatas[i + 1]);
                    }
                    else
                    {
                        realDatas[retIndex] = (Int16)(-1 * iDatas[i]);
                        realDatas[retIndex + 1] = qDatas[i + 1];
                    }
                    flag = !flag;
                    retIndex += 2;
                }
            }
        }




        /// <summary>
        /// 将IQ数据转换为实数
        /// </summary>
        /// <param name="iDatas">I数据</param>
        /// <param name="qDatas">Q数据</param>
        /// <returns>实数数据存放数组</returns>
        /// <exception cref="ArgumentNullException">原始数组为null异常</exception>
        public static double[] IQMerge(double[] iDatas, double[] qDatas)
        {
            if (iDatas == null)
            {
                throw new ArgumentNullException(nameof(iDatas));
            }

            if (qDatas == null)
            {
                throw new ArgumentNullException(nameof(qDatas));
            }

            int count = iDatas.Length > qDatas.Length ? iDatas.Length : qDatas.Length;
            double[] realDatas = new double[count];
            IQMerge(iDatas, qDatas, 0, realDatas, 0, count);
            return realDatas;
        }

        /// <summary>
        /// 将IQ数据转换为实数
        /// </summary>
        /// <param name="iDatas">I数据</param>
        /// <param name="qDatas">Q数据</param>
        /// <param name="realDatas">实数数据存放数组</param>
        /// <exception cref="ArgumentNullException">原始数组或实数数组为null异常</exception>
        public static void IQMerge(double[] iDatas, double[] qDatas, double[] realDatas)
        {
            if (iDatas == null)
            {
                throw new ArgumentNullException(nameof(iDatas));
            }

            if (qDatas == null)
            {
                throw new ArgumentNullException(nameof(qDatas));
            }

            if (realDatas == null)
            {
                throw new ArgumentNullException(nameof(realDatas));
            }

            int len = iDatas.Length < qDatas.Length ? iDatas.Length : qDatas.Length;
            if (len > realDatas.Length)
            {
                len = realDatas.Length;
            }

            int count = len - (len % 2);//保证count值是个偶数
            IQMerge(iDatas, qDatas, 0, realDatas, 0, count);
        }

        /// <summary>
        /// 将IQ数据转换为实数
        /// </summary>
        /// <param name="iDatas">I数据</param>
        /// <param name="qDatas">Q数据</param>
        /// <param name="sourceIndex">IQ数据起始位置</param>
        /// <param name="realDatas">实数数据存放数组</param>
        /// <param name="destinationIndex">实数数据存放起始位置</param>
        /// <param name="length">转换数据长度</param>
        /// <exception cref="ArgumentNullException">原始数组或实数数组为null异常</exception>
        /// <exception cref="ArgumentOutOfRangeException">起始位置或长度超出范围异常</exception>
        public static void IQMerge(double[] iDatas, double[] qDatas, int sourceIndex, double[] realDatas, int destinationIndex, int length)
        {
            if (iDatas == null)
            {
                throw new ArgumentNullException(nameof(iDatas));
            }

            if (qDatas == null)
            {
                throw new ArgumentNullException(nameof(qDatas));
            }

            if (realDatas == null)
            {
                throw new ArgumentNullException(nameof(realDatas));
            }

            if (sourceIndex < 0)
            {
                throw new ArgumentOutOfRangeException("原数据起始索引不能小于0", nameof(sourceIndex));
            }

            if (destinationIndex < 0)
            {
                throw new ArgumentOutOfRangeException("结果数据起始索引不能小于0", nameof(destinationIndex));
            }

            int sourceEndIndex = sourceIndex + length;
            if (sourceEndIndex > iDatas.Length ||
                sourceEndIndex > qDatas.Length ||
                destinationIndex + length > realDatas.Length)
            {
                throw new ArgumentOutOfRangeException("处理的数据长度超出原数组长度或结果数组长度", nameof(length));
            }

            //如果数据长度超过门限个点,则用多线程并处处理,否则就单线程处理
            if (HasParallel(length))
            {
                int parallelCount = Environment.ProcessorCount;
                int segLength = ((length / 4) / parallelCount) * 4;
                Parallel.For(0, parallelCount, (segIndex) =>
                {
                    int startIndex = sourceIndex + segIndex * segLength;
                    bool hasProcessTail = false;
                    int endIndex;
                    if (segIndex + 1 == parallelCount)
                    {
                        endIndex = sourceIndex + length;//最后一个线程,要把不能平均分配的都处理掉
                        if ((endIndex - startIndex) % 2 != 0)
                        {
                            endIndex -= 1;
                            hasProcessTail = true;
                        }
                    }
                    else
                    {
                        endIndex = startIndex + segLength;//非最后一个线程,只处理对应段数据
                    }
                    //Console.WriteLine($"第{segIndex}段:{startIndex}-{endIndex}        hasProcessTail:{hasProcessTail.ToString()}");
                    bool flag = true;
                    int retIndex = destinationIndex + segIndex * segLength;
                    for (int i = startIndex; i < endIndex; i += 2)
                    {
                        if (flag)
                        {
                            realDatas[retIndex] = iDatas[i];
                            realDatas[retIndex + 1] = -1 * qDatas[i + 1];
                        }
                        else
                        {
                            realDatas[retIndex] = -1 * iDatas[i];
                            realDatas[retIndex + 1] = qDatas[i + 1];
                        }
                        flag = !flag;
                        retIndex += 2;
                    }

                    if (hasProcessTail)
                    {
                        if (flag)
                        {
                            realDatas[retIndex] = iDatas[endIndex];
                        }
                        else
                        {
                            realDatas[retIndex] = -1 * iDatas[endIndex];
                        }
                    }
                });
            }
            else
            {
                int endIndex = sourceEndIndex;
                bool hasProcessTail = false;
                if ((endIndex - sourceIndex) % 2 != 0)
                {
                    endIndex -= 1;
                    hasProcessTail = true;
                }

                bool flag = true;
                int retIndex = destinationIndex;
                for (int i = sourceIndex; i < endIndex; i += 2)
                {
                    if (flag)
                    {
                        realDatas[retIndex] = iDatas[i];
                        realDatas[retIndex + 1] = -1 * qDatas[i + 1];
                    }
                    else
                    {
                        realDatas[retIndex] = -1 * iDatas[i];
                        realDatas[retIndex + 1] = qDatas[i + 1];
                    }
                    flag = !flag;
                    retIndex += 2;
                }

                if (hasProcessTail)
                {
                    if (flag)
                    {
                        realDatas[retIndex] = iDatas[endIndex];
                    }
                    else
                    {
                        realDatas[retIndex] = -1 * iDatas[endIndex];
                    }
                }
            }
        }




        /// <summary>
        /// 将复数形式的IQ数据转换为实数
        /// </summary>
        /// <param name="complex">复数形式的IQ数据</param>
        /// <returns>实数数据存放数组</returns>
        /// <exception cref="ArgumentNullException">原始数组为null异常</exception>
        public static double[] IQMerge(Complex[] complex)
        {
            if (complex == null)
            {
                throw new ArgumentNullException(nameof(complex));
            }

            double[] realDatas = new double[complex.Length];
            IQMerge(complex, 0, realDatas, 0, complex.Length);
            return realDatas;
        }

        /// <summary>
        /// 将复数形式的IQ数据转换为实数
        /// </summary>
        /// <param name="complex">复数形式的IQ数据</param>
        /// <param name="realDatas">实数数据存放数组</param>
        /// <exception cref="ArgumentNullException">原始数组或实数数组为null异常</exception>
        public static void IQMerge(Complex[] complex, double[] realDatas)
        {
            if (complex == null)
            {
                throw new ArgumentNullException(nameof(complex));
            }

            if (realDatas == null)
            {
                throw new ArgumentNullException(nameof(realDatas));
            }

            int len = realDatas.Length < realDatas.Length ? realDatas.Length : realDatas.Length;
            int count = len - (len % 2);//保证count值是个偶数
            IQMerge(complex, 0, realDatas, 0, count);
        }

        /// <summary>
        /// 将复数形式的IQ数据转换为实数
        /// </summary>
        /// <param name="complex">复数形式的IQ数据</param>
        /// <param name="sourceIndex">复数形式的IQ数据起始位置</param>
        /// <param name="realDatas">实数数据存放数组</param>
        /// <param name="destinationIndex">实数数据存放起始位置</param>
        /// <param name="length">转换数据长度</param>
        /// <exception cref="ArgumentNullException">原始数组或实数数组为null异常</exception>
        /// <exception cref="ArgumentOutOfRangeException">起始位置或长度超出范围异常</exception>
        public static void IQMerge(Complex[] complex, int sourceIndex, double[] realDatas, int destinationIndex, int length)
        {
            if (complex == null)
            {
                throw new ArgumentNullException("原数据不能为null", nameof(complex));
            }

            if (realDatas == null)
            {
                throw new ArgumentNullException("结果数据不能为null", nameof(realDatas));
            }

            if (sourceIndex < 0)
            {
                throw new ArgumentOutOfRangeException("原数据起始索引不能小于0", nameof(sourceIndex));
            }

            if (destinationIndex < 0)
            {
                throw new ArgumentOutOfRangeException("结果数据起始索引不能小于0", nameof(destinationIndex));
            }

            if (sourceIndex + length > complex.Length || destinationIndex + length > realDatas.Length)
            {
                throw new ArgumentOutOfRangeException("处理的数据长度超出原数组长度或结果数组长度", nameof(length));
            }

            //如果数据长度超过门限个点,则用多线程并处处理,否则就单线程处理
            if (HasParallel(length))
            {
                int parallelCount = Environment.ProcessorCount;
                int segLength = ((length / 4) / parallelCount) * 4;
                Parallel.For(0, parallelCount, (segIndex) =>
                {
                    int startIndex = sourceIndex + segIndex * segLength;
                    bool hasProcessTail = false;
                    int endIndex;
                    if (segIndex + 1 == parallelCount)
                    {
                        endIndex = sourceIndex + length;//最后一个线程,要把不能平均分配的都处理掉
                        if ((endIndex - startIndex) % 2 != 0)
                        {
                            endIndex -= 1;
                            hasProcessTail = true;
                        }
                    }
                    else
                    {
                        endIndex = startIndex + segLength;//非最后一个线程,只处理对应段数据
                    }
                    //Console.WriteLine($"第{segIndex}段:{startIndex}-{endIndex}");
                    bool flag = true;
                    int retIndex = destinationIndex + segIndex * segLength;
                    for (int i = startIndex; i < endIndex; i += 2)
                    {
                        if (flag)
                        {
                            realDatas[retIndex] = complex[i].Real;
                            realDatas[retIndex + 1] = -1 * complex[i + 1].Imaginary;
                        }
                        else
                        {
                            realDatas[retIndex] = -1 * complex[i].Real;
                            realDatas[retIndex + 1] = complex[i + 1].Imaginary;
                        }
                        flag = !flag;
                        retIndex += 2;
                    }

                    if (hasProcessTail)
                    {
                        if (flag)
                        {
                            realDatas[retIndex] = complex[endIndex].Real;
                        }
                        else
                        {
                            realDatas[retIndex] = -1 * complex[endIndex].Real;
                        }
                    }
                });
            }
            else
            {
                int endIndex = sourceIndex + length;
                bool hasProcessTail = false;
                if ((endIndex - sourceIndex) % 2 != 0)
                {
                    endIndex -= 1;
                    hasProcessTail = true;
                }

                bool flag = true;
                int retIndex = destinationIndex;
                for (int i = sourceIndex; i < endIndex; i += 2)
                {
                    if (flag)
                    {
                        realDatas[retIndex] = complex[i].Real;
                        realDatas[retIndex + 1] = -1 * complex[i + 1].Imaginary;
                    }
                    else
                    {
                        realDatas[retIndex] = -1 * complex[i].Real;
                        realDatas[retIndex + 1] = complex[i + 1].Imaginary;
                    }
                    flag = !flag;
                    retIndex += 2;
                }

                if (hasProcessTail)
                {
                    if (flag)
                    {
                        realDatas[retIndex] = complex[endIndex].Real;
                    }
                    else
                    {
                        realDatas[retIndex] = -1 * complex[endIndex].Real;
                    }
                }
            }
        }

        #endregion


        /*

        #region Real转换为IQ

        public static void RealToIQ<T>(IList<T> realDatas, int sourceIndex, IList<T> iDatas, IList<T> qDatas, int destinationIndex, int length)
        {
            if (realDatas == null)
            {
                throw new ArgumentNullException(nameof(realDatas));
            }

            if (qDatas == null)
            {
                throw new ArgumentNullException(nameof(qDatas));
            }

            if (qDatas == null)
            {
                throw new ArgumentNullException(nameof(qDatas));
            }

            if (sourceIndex < 0)
            {
                throw new ArgumentOutOfRangeException("原数据起始索引不能小于0", nameof(sourceIndex));
            }

            if (destinationIndex < 0)
            {
                throw new ArgumentOutOfRangeException("结果数据起始索引不能小于0", nameof(destinationIndex));
            }

            int retMinCount = qDatas.Count < qDatas.Count ? qDatas.Count : qDatas.Count;
            if (sourceIndex + length > realDatas.Count ||
                destinationIndex + length > retMinCount)
            {
                throw new ArgumentOutOfRangeException("处理的数据长度超出原数组长度或结果数组长度", nameof(length));
            }


        }


        #endregion

        */

    }
}
